En djupgÄende guide till Cross-Origin Resource Sharing (CORS) och preflight-förfrÄgningar. LÀr dig hantera CORS-problem och sÀkra dina webbapplikationer.
Avmystifiering av CORS: En djupdykning i hantering av JavaScript Preflight-förfrÄgningar
I den stÀndigt vÀxande vÀrlden av webbutveckling Àr sÀkerhet av yttersta vikt. Cross-Origin Resource Sharing (CORS) Àr en avgörande sÀkerhetsmekanism som implementeras av webblÀsare för att begrÀnsa webbsidor frÄn att göra förfrÄgningar till en annan domÀn Àn den som serverade webbsidan. Detta Àr en grundlÀggande sÀkerhetsfunktion som Àr utformad för att förhindra skadliga webbplatser frÄn att komma Ät kÀnslig data. Denna omfattande guide kommer att fördjupa sig i komplexiteten hos CORS, med specifikt fokus pÄ hantering av preflight-förfrÄgningar. Vi kommer att utforska 'varför', 'vad' och 'hur' gÀllande CORS, och ge praktiska exempel och lösningar pÄ vanliga problem som utvecklare vÀrlden över stöter pÄ.
FörstÄ Same-Origin Policy
KÀrnan i CORS Àr Same-Origin Policy (SOP). Denna policy Àr en sÀkerhetsmekanism pÄ webblÀsarnivÄ som begrÀnsar skript som körs pÄ ett ursprung frÄn att komma Ät resurser frÄn ett annat ursprung. Ett ursprung definieras av protokollet (t.ex. HTTP eller HTTPS), domÀnen (t.ex. example.com) och porten (t.ex. 80 eller 443). TvÄ URL:er har samma ursprung om dessa tre komponenter matchar exakt.
Till exempel:
https://www.example.com/app1/index.html
ochhttps://www.example.com/app2/index.html
har samma ursprung (samma protokoll, domÀn och port).https://www.example.com/index.html
ochhttp://www.example.com/index.html
har olika ursprung (olika protokoll).https://www.example.com/index.html
ochhttps://api.example.com/index.html
har olika ursprung (olika subdomÀner anses vara olika domÀner).https://www.example.com:8080/index.html
ochhttps://www.example.com/index.html
har olika ursprung (olika portar).
SOP Ă€r utformad för att förhindra skadliga skript pĂ„ en webbplats frĂ„n att komma Ă„t kĂ€nslig data, som cookies eller anvĂ€ndarautentiseringsinformation, pĂ„ en annan webbplats. Ăven om det Ă€r avgörande för sĂ€kerheten kan SOP ocksĂ„ vara restriktivt, sĂ€rskilt nĂ€r legitima förfrĂ„gningar mellan olika ursprung behövs.
Vad Àr Cross-Origin Resource Sharing (CORS)?
CORS Àr en mekanism som tillÄter servrar att specificera vilka ursprung (domÀner, scheman eller portar) som har tillÄtelse att komma Ät deras resurser. Det lÀttar i grunden pÄ SOP, vilket tillÄter kontrollerad Ätkomst mellan olika ursprung. CORS implementeras med hjÀlp av HTTP-rubriker som utbyts mellan klienten (vanligtvis en webblÀsare) och servern.
NÀr en webblÀsare gör en förfrÄgan mellan olika ursprung (dvs. en förfrÄgan till ett annat ursprung Àn den nuvarande sidan), kontrollerar den först om servern tillÄter förfrÄgan. Detta görs genom att undersöka rubriken Access-Control-Allow-Origin
i serverns svar. Om förfrÄgans ursprung finns med i denna rubrik (eller om rubriken Àr instÀlld pÄ *
, vilket tillÄter alla ursprung), tillÄter webblÀsaren att förfrÄgan fortsÀtter. Annars blockerar webblÀsaren förfrÄgan och förhindrar JavaScript-koden frÄn att komma Ät svarsdatan.
Rollen för Preflight-förfrÄgningar
För vissa typer av förfrÄgningar mellan olika ursprung initierar webblÀsaren en preflight-förfrÄgan. Detta Àr en OPTIONS
-förfrÄgan som skickas till servern före den faktiska förfrÄgan. Syftet med preflight-förfrÄgan Àr att avgöra om servern Àr villig att acceptera den faktiska förfrÄgan. Servern svarar pÄ preflight-förfrÄgan med information om tillÄtna metoder, rubriker och andra begrÀnsningar.
Preflight-förfrÄgningar utlöses nÀr förfrÄgan mellan olika ursprung uppfyller nÄgot av följande villkor:
- FörfrÄgans metod Àr inte
GET
,HEAD
ellerPOST
. - FörfrÄgan inkluderar anpassade rubriker (dvs. andra rubriker Àn de som automatiskt lÀggs till av webblÀsaren).
- Rubriken
Content-Type
Àr instÀlld pÄ nÄgot annat Ànapplication/x-www-form-urlencoded
,multipart/form-data
ellertext/plain
. - FörfrÄgan anvÀnder
ReadableStream
-objekt i sin body.
Till exempel kommer en PUT
-förfrÄgan med Content-Type
som application/json
att utlösa en preflight-förfrÄgan eftersom den anvÀnder en annan metod Àn de tillÄtna och en potentiellt otillÄten innehÄllstyp.
Varför Preflight-förfrÄgningar?
Preflight-förfrÄgningar Àr viktiga för sÀkerheten eftersom de ger servern en möjlighet att avvisa potentiellt skadliga förfrÄgningar mellan olika ursprung innan de exekveras. Utan preflight-förfrÄgningar skulle en skadlig webbplats potentiellt kunna skicka godtyckliga förfrÄgningar till en server utan serverns uttryckliga samtycke. En preflight-förfrÄgan tillÄter servern att validera att förfrÄgan Àr acceptabel och förhindrar potentiellt skadliga operationer.
Hantering av Preflight-förfrÄgningar pÄ serversidan
Att korrekt hantera preflight-förfrÄgningar Àr avgörande för att sÀkerstÀlla att din webbapplikation fungerar korrekt och sÀkert. Servern mÄste svara pÄ OPTIONS
-förfrÄgan med lÀmpliga CORS-rubriker för att indikera om den faktiska förfrÄgan Àr tillÄten.
HÀr Àr en genomgÄng av de viktigaste CORS-rubrikerna som anvÀnds i preflight-svar:
Access-Control-Allow-Origin
: Denna rubrik specificerar det eller de ursprung som tillÄts komma Ät resursen. Den kan stÀllas in pÄ ett specifikt ursprung (t.ex.https://www.example.com
) eller pÄ*
för att tillÄta alla ursprung. Att anvÀnda*
rekommenderas dock generellt inte av sÀkerhetsskÀl, sÀrskilt om servern hanterar kÀnslig data.Access-Control-Allow-Methods
: Denna rubrik specificerar de HTTP-metoder som Àr tillÄtna för förfrÄgan mellan olika ursprung (t.ex.GET
,POST
,PUT
,DELETE
).Access-Control-Allow-Headers
: Denna rubrik specificerar listan över icke-standardiserade HTTP-rubriker som Àr tillÄtna i den faktiska förfrÄgan. Detta Àr nödvÀndigt om klienten skickar anpassade rubriker, sÄsomX-Custom-Header
ellerAuthorization
.Access-Control-Allow-Credentials
: Denna rubrik indikerar om den faktiska förfrÄgan kan inkludera autentiseringsuppgifter, sÄsom cookies eller auktorisationsrubriker. Den mÄste vara satt tilltrue
om klientkoden skickar autentiseringsuppgifter och servern ska acceptera dem. Notera: nÀr denna rubrik Àr satt till `true`, kan `Access-Control-Allow-Origin` *inte* vara satt till `*`. Du mÄste specificera ursprunget.Access-Control-Max-Age
: Denna rubrik specificerar den maximala tiden (i sekunder) som webblÀsaren kan cacha preflight-svaret. Detta kan hjÀlpa till att förbÀttra prestandan genom att minska antalet preflight-förfrÄgningar som skickas.
Exempel: Hantering av Preflight-förfrÄgningar i Node.js med Express
HÀr Àr ett exempel pÄ hur man hanterar preflight-förfrÄgningar i en Node.js-applikation med Express-ramverket:
const express = require('express');
const cors = require('cors');
const app = express();
// Aktivera CORS för alla ursprung (endast för utvecklingssyften!)
// I produktion, specificera tillÄtna ursprung för bÀttre sÀkerhet.
app.use(cors()); //eller app.use(cors({origin: 'https://www.example.com'}));
// Route för att hantera OPTIONS-förfrÄgningar (preflight)
app.options('/data', cors()); // Aktivera CORS för en enskild route. Eller specificera ursprung: cors({origin: 'https://www.example.com'})
// Route för att hantera GET-förfrÄgningar
app.get('/data', (req, res) => {
res.json({ message: 'Detta Àr data frÄn ett annat ursprung!' });
});
// Route för att hantera en preflight och en post-förfrÄgan
app.options('/resource', cors()); // aktivera pre-flight-förfrÄgan för DELETE-förfrÄgan
app.delete('/resource', cors(), (req, res, next) => {
res.send('ta bort resurs')
})
const port = 3000;
app.listen(port, () => {
console.log(`Servern lyssnar pÄ port ${port}`);
});
I detta exempel anvÀnder vi cors
-middleware för att hantera CORS-förfrÄgningar. För mer detaljerad kontroll kan CORS aktiveras per route. Notera: i produktion rekommenderas det starkt att specificera tillÄtna ursprung med origin
-alternativet istÀllet för att tillÄta alla ursprung. Att tillÄta alla ursprung med *
kan utsÀtta din applikation för sÀkerhetssÄrbarheter.
Exempel: Hantering av Preflight-förfrÄgningar i Python med Flask
HÀr Àr ett exempel pÄ hur man hanterar preflight-förfrÄgningar i en Python-applikation med Flask-ramverket och tillÀgget flask_cors
:
from flask import Flask, jsonify
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app) # Aktivera CORS för alla routes
@app.route('/data')
@cross_origin()
def get_data():
data = {"message": "Detta Àr data frÄn ett annat ursprung!"}
return jsonify(data)
if __name__ == '__main__':
app.run(debug=True)
Detta Àr den enklaste anvÀndningen. Liksom tidigare kan ursprungen begrÀnsas. Se flask-cors-dokumentationen för detaljer.
Exempel: Hantering av Preflight-förfrÄgningar i Java med Spring Boot
HÀr Àr ett exempel pÄ hur man hanterar preflight-förfrÄgningar i en Java-applikation med Spring Boot:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class CorsApplication {
public static void main(String[] args) {
SpringApplication.run(CorsApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data").allowedOrigins("http://localhost:8080");
}
};
}
}
Och motsvarande controller:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DataController {
@GetMapping("/data")
public String getData() {
return "Detta Àr data frÄn ett annat ursprung!";
}
}
Vanliga CORS-problem och lösningar
Trots sin betydelse kan CORS ofta vara en kÀlla till frustration för utvecklare. HÀr Àr nÄgra vanliga CORS-problem och deras lösningar:
-
Fel: "No 'Access-Control-Allow-Origin' header is present on the requested resource."
Detta fel indikerar att servern inte returnerar rubriken
Access-Control-Allow-Origin
i sitt svar. För att ÄtgÀrda detta, se till att servern Àr konfigurerad för att inkludera rubriken och att den Àr instÀlld pÄ rÀtt ursprung eller pÄ*
(om lÀmpligt).Lösning: Konfigurera servern för att inkludera rubriken `Access-Control-Allow-Origin` i sitt svar, och stÀll in den pÄ den anropande webbplatsens ursprung eller pÄ `*` för att tillÄta alla ursprung (anvÀnd med försiktighet).
-
Fel: "Response to preflight request doesn't pass access control check: Request header field X-Custom-Header is not allowed by Access-Control-Allow-Headers in preflight response."
Detta fel indikerar att servern inte tillÄter den anpassade rubriken (
X-Custom-Header
i detta exempel) i förfrÄgan mellan olika ursprung. För att ÄtgÀrda detta, se till att servern inkluderar rubriken iAccess-Control-Allow-Headers
-rubriken i preflight-svaret.Lösning: LÀgg till den anpassade rubriken (t.ex. `X-Custom-Header`) i `Access-Control-Allow-Headers`-rubriken i serverns preflight-svar.
-
Fel: "Credentials flag is 'true', but the 'Access-Control-Allow-Origin' header is '*'."
NĂ€r rubriken
Access-Control-Allow-Credentials
Ă€r satt tilltrue
mÄste rubrikenAccess-Control-Allow-Origin
vara satt till ett specifikt ursprung, inte*
. Detta beror pÄ att det skulle vara en sÀkerhetsrisk att tillÄta autentiseringsuppgifter frÄn alla ursprung.Lösning: NÀr du anvÀnder autentiseringsuppgifter, stÀll in `Access-Control-Allow-Origin` pÄ ett specifikt ursprung istÀllet för `*`.
-
Preflight-förfrÄgan skickas inte.
Dubbelkolla att din JavaScript-kod inkluderar egenskapen `credentials: 'include'`. Kontrollera ocksÄ att din server tillÄter `Access-Control-Allow-Credentials: true`.
-
Motstridiga konfigurationer mellan server och klient.
Kontrollera noggrant din server-side CORS-konfiguration tillsammans med klient-side-instÀllningarna. Olikheter (t.ex. att servern bara tillÄter GET-förfrÄgningar men klienten skickar POST) kommer att orsaka CORS-fel.
CORS och bÀsta praxis för sÀkerhet
Medan CORS tillÄter kontrollerad Ätkomst mellan olika ursprung Àr det viktigt att följa bÀsta praxis för sÀkerhet för att förhindra sÄrbarheter:
- Undvik att anvÀnda
*
iAccess-Control-Allow-Origin
-rubriken i produktion. Detta tillĂ„ter alla ursprung att komma Ă„t dina resurser, vilket kan vara en sĂ€kerhetsrisk. Specificera istĂ€llet exakt vilka ursprung som Ă€r tillĂ„tna. - ĂvervĂ€g noggrant vilka metoder och rubriker som ska tillĂ„tas. TillĂ„t endast de metoder och rubriker som Ă€r absolut nödvĂ€ndiga för att din applikation ska fungera korrekt.
- Implementera korrekta autentiserings- och auktoriseringsmekanismer. CORS Àr inte en ersÀttning för autentisering och auktorisering. Se till att ditt API Àr skyddat av lÀmpliga sÀkerhetsÄtgÀrder.
- Validera och sanera all anvÀndarinput. Detta hjÀlper till att förhindra cross-site scripting (XSS)-attacker och andra sÄrbarheter.
- HÄll din server-side CORS-konfiguration uppdaterad. Granska och uppdatera regelbundet din CORS-konfiguration för att sÀkerstÀlla att den överensstÀmmer med din applikations sÀkerhetskrav.
CORS i olika utvecklingsmiljöer
CORS-problem kan yttra sig olika i olika utvecklingsmiljöer och teknologier. HÀr Àr en titt pÄ hur man kan hantera CORS i nÄgra vanliga scenarier:
Lokala utvecklingsmiljöer
Under lokal utveckling kan CORS-problem vara sÀrskilt irriterande. WebblÀsare blockerar ofta förfrÄgningar frÄn din lokala utvecklingsserver (t.ex. localhost:3000
) till ett fjÀrr-API. Flera tekniker kan lindra detta:
- WebblÀsartillÀgg: TillÀgg som "Allow CORS: Access-Control-Allow-Origin" kan tillfÀlligt inaktivera CORS-begrÀnsningar för testÀndamÄl. AnvÀnd dock *aldrig* dessa i produktion.
- Proxyservrar: Konfigurera en proxyserver som vidarebefordrar förfrÄgningar frÄn din lokala utvecklingsserver till fjÀrr-API:et. Detta gör effektivt förfrÄgningarna till "samma ursprung" ur webblÀsarens perspektiv. Verktyg som
http-proxy-middleware
(för Node.js) Ă€r anvĂ€ndbara för detta. - Konfigurera serverns CORS: Ăven under utveckling Ă€r det bĂ€sta praxis att konfigurera din API-server för att explicit tillĂ„ta förfrĂ„gningar frĂ„n ditt lokala utvecklingsursprung (t.ex.
http://localhost:3000
). Detta simulerar en verklig CORS-konfiguration och hjÀlper dig att upptÀcka problem tidigt.
Serverlösa miljöer (t.ex. AWS Lambda, Google Cloud Functions)
Serverlösa funktioner krÀver ofta noggrann CORS-konfiguration. MÄnga serverlösa plattformar har inbyggt CORS-stöd, men det Àr avgörande att konfigurera det korrekt:
- Plattformsspecifika instÀllningar: AnvÀnd plattformens inbyggda konfigurationsalternativ för CORS. AWS Lambda tillÄter dig till exempel att specificera tillÄtna ursprung, metoder och rubriker direkt i API Gateway-instÀllningarna.
- Middleware/Bibliotek: För större flexibilitet kan du anvÀnda middleware eller bibliotek för att hantera CORS i din serverlösa funktionskod. Detta liknar de metoder som anvÀnds i traditionella servermiljöer (t.ex. att anvÀnda
cors
-paketet i Node.js Lambda-funktioner). - TÀnk pÄ
OPTIONS
-metoden: Se till att din serverlösa funktion hanterarOPTIONS
-förfrÄgningar korrekt. Detta innebÀr ofta att skapa en separat route som returnerar lÀmpliga CORS-rubriker.
Mobilappsutveckling (t.ex. React Native, Flutter)
CORS Àr mindre av ett direkt bekymmer för native mobilappar (Android, iOS), eftersom de vanligtvis inte upprÀtthÄller same-origin policy pÄ samma sÀtt som webblÀsare. CORS kan dock fortfarande vara relevant om din mobilapp anvÀnder en webbvy för att visa webbinnehÄll eller om du anvÀnder ramverk som React Native eller Flutter som utnyttjar JavaScript:
- Webbvyer: Om din mobilapp anvÀnder en webbvy för att visa webbinnehÄll gÀller samma CORS-regler som i en webblÀsare. Konfigurera din server för att tillÄta förfrÄgningar frÄn webbinnehÄllets ursprung.
- React Native/Flutter: Dessa ramverk anvĂ€nder JavaScript för att göra API-förfrĂ„gningar. Ăven om den native miljön kanske inte upprĂ€tthĂ„ller CORS direkt, kan de underliggande HTTP-klienterna (t.ex.
fetch
) fortfarande uppvisa CORS-liknande beteende i vissa situationer. - Native HTTP-klienter: NÀr man gör API-förfrÄgningar direkt frÄn native kod (t.ex. med OkHttp pÄ Android eller URLSession pÄ iOS) Àr CORS generellt sett inte en faktor. Du mÄste dock fortfarande övervÀga bÀsta praxis för sÀkerhet, sÄsom korrekt autentisering och auktorisering.
Globala övervÀganden för CORS-konfiguration
NÀr du konfigurerar CORS för en globalt tillgÀnglig applikation Àr det avgörande att ta hÀnsyn till faktorer som:
- DatasuverÀnitet: Regelverk i vissa regioner krÀver att data lagras inom regionen. CORS kan vara inblandat vid Ätkomst till resurser över grÀnserna, vilket potentiellt kan strida mot lagar om datalagring.
- Regionala sÀkerhetspolicyer: Olika lÀnder kan ha olika cybersÀkerhetsregler och riktlinjer som pÄverkar hur CORS ska implementeras och sÀkras.
- Content Delivery Networks (CDN): Se till att ditt CDN Àr korrekt konfigurerat för att skicka igenom de nödvÀndiga CORS-rubrikerna. Felaktigt konfigurerade CDN kan ta bort CORS-rubriker, vilket leder till ovÀntade fel.
- Lastbalanserare och proxyservrar: Verifiera att eventuella lastbalanserare eller omvÀnda proxyservrar i din infrastruktur hanterar preflight-förfrÄgningar korrekt och skickar igenom CORS-rubriker.
- FlersprĂ„kigt stöd: ĂvervĂ€g hur CORS interagerar med din applikations strategier för internationalisering (i18n) och lokalisering (l10n). Se till att CORS-policyer Ă€r konsekventa över olika sprĂ„kversioner av din applikation.
Testning och felsökning av CORS
Att effektivt testa och felsöka CORS Àr avgörande. HÀr Àr nÄgra tekniker:
- WebblÀsarens utvecklarverktyg: WebblÀsarens utvecklarkonsol Àr ditt första stopp. Fliken "Network" visar preflight-förfrÄgningar och svaren, vilket avslöjar om CORS-rubriker finns och Àr korrekt konfigurerade.
- Kommandoradsverktyget `curl`: AnvÀnd `curl -v -X OPTIONS
` för att manuellt skicka preflight-förfrÄgningar och inspektera serverns svarsrubriker. - Online CORS-kontrollverktyg: Det finns mÄnga onlineverktyg som kan hjÀlpa till att validera din CORS-konfiguration. Sök bara efter "CORS checker."
- Enhets- och integrationstester: Skriv automatiserade tester för att verifiera att din CORS-konfiguration fungerar som förvÀntat. Dessa tester bör tÀcka bÄde lyckade förfrÄgningar mellan olika ursprung och scenarier dÀr CORS ska blockera Ätkomst.
- Loggning och övervakning: Implementera loggning för att spĂ„ra CORS-relaterade hĂ€ndelser, sĂ„som preflight-förfrĂ„gningar och blockerade förfrĂ„gningar. Ăvervaka dina loggar för misstĂ€nkt aktivitet eller konfigurationsfel.
Slutsats
Cross-Origin Resource Sharing (CORS) Àr en vital sÀkerhetsmekanism som möjliggör kontrollerad Ätkomst till webbresurser mellan olika ursprung. Att förstÄ hur CORS fungerar, sÀrskilt preflight-förfrÄgningar, Àr avgörande för att bygga sÀkra och pÄlitliga webbapplikationer. Genom att följa de bÀsta metoderna som beskrivs i denna guide kan du effektivt hantera CORS-problem och skydda din applikation frÄn potentiella sÄrbarheter. Kom ihÄg att alltid prioritera sÀkerhet och noggrant övervÀga konsekvenserna av din CORS-konfiguration.
I takt med att webbutvecklingen utvecklas kommer CORS att fortsÀtta vara en kritisk aspekt av webbsÀkerhet. Att hÄlla sig informerad om de senaste bÀsta metoderna och teknikerna för CORS Àr avgörande för att bygga sÀkra och globalt tillgÀngliga webbapplikationer.